﻿using ShevaCore.Interfaces;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace ShevaCore.Input
{
    /// <summary>
    /// Trida ovladace mysi.
    /// </summary>
    public class XMouse : IUpdateAble
    {
        /// <summary>Predchozi stav mysi.</summary>
        private MouseState _PreviousState;
        /// <summary>Udalost vyvolana kliknutim tlacitka.</summary>
        public event OnMouseButtonDelegate OnMouseButtonClick;
        /// <summary>Udalost volana zmacknutim tlacitka.</summary>
        public event OnMouseButtonDelegate OnMouseButtonDown;
        /// <summary>Udalost vyvolana uvolnenim tlacitka.</summary>
        public event OnMouseButtonDelegate OnMouseButtonUp;
        /// <summary>Udalost volana pri zmene polohy mysi.</summary>
        public event OnMouseMoveDelegate OnMouseMove;
        /// <summary>Udalost volana zmacknutim tlacitka.</summary>
        public event OnMouseButtonDelegate OnMouseButtonHold;
        /// <summary>Casy zmacknuti tlacitka.</summary>
        private GameTime[] _DownButtonTimes;
        /// <summary>Prodleva odkdy se uvazuje zamacknuti mysi.</summary>
        public float ButtonDelay = 1;

        /// <summary>
        /// Konstruktor.
        /// </summary>
        public XMouse()
        {
            this._PreviousState = Mouse.GetState();
            this._DownButtonTimes = new GameTime[] { new GameTime(), new GameTime(), new GameTime() };
        }

        #region IUpdateAble Members
        /// <summary>
        /// Metoda update.
        /// </summary>
        /// <param name="deltaT"></param>
        public void Update(GameTime time)
        {
            MouseState actualState = Mouse.GetState();

            if (this._PreviousState.X != actualState.X || this._PreviousState.Y != actualState.Y)
                if (this.OnMouseMove != null)
                    this.OnMouseMove(this, new Vector2(actualState.X, actualState.Y));

            if (actualState.LeftButton != this._PreviousState.LeftButton)
            {
                if (actualState.LeftButton == ButtonState.Pressed)
                {
                    if (this.OnMouseButtonDown != null)
                        this.OnMouseButtonDown(this, MouseButton.Left);

                    this._DownButtonTimes[0] = time;
                }
                else
                {
                    if (this.OnMouseButtonUp != null)
                        this.OnMouseButtonUp(this, MouseButton.Left);
                    if (this.OnMouseButtonClick != null)
                        this.OnMouseButtonClick(this, MouseButton.Left);
                }
            }
            else
                if (actualState.LeftButton == ButtonState.Pressed &&
                    time.ElapsedGameTime.Seconds - this._DownButtonTimes[0].ElapsedGameTime.Seconds > this.ButtonDelay)
                    if (this.OnMouseButtonHold != null)
                        this.OnMouseButtonHold(this, MouseButton.Left);

            if (actualState.RightButton != this._PreviousState.RightButton)
            {
                if (actualState.RightButton == ButtonState.Pressed)
                {
                    if (this.OnMouseButtonDown != null)
                        this.OnMouseButtonDown(this, MouseButton.Right);
                }
                else
                {
                    if (this.OnMouseButtonUp != null)
                        this.OnMouseButtonUp(this, MouseButton.Right);
                    if (this.OnMouseButtonClick != null)
                        this.OnMouseButtonClick(this, MouseButton.Right);
                }
            }
            else
                if (actualState.RightButton == ButtonState.Pressed)
                    if (this.OnMouseButtonHold != null)
                        this.OnMouseButtonHold(this, MouseButton.Right);

            if (actualState.MiddleButton != this._PreviousState.MiddleButton)
            {
                if (actualState.MiddleButton == ButtonState.Pressed)
                {
                    if (this.OnMouseButtonDown != null)
                        this.OnMouseButtonDown(this, MouseButton.Middle);
                }
                else
                {
                    if (this.OnMouseButtonUp != null)
                        this.OnMouseButtonUp(this, MouseButton.Middle);
                    if (this.OnMouseButtonClick != null)
                        this.OnMouseButtonClick(this, MouseButton.Middle);
                }
            }
            else
                if (actualState.MiddleButton == ButtonState.Pressed)
                    if (this.OnMouseButtonHold != null)
                        this.OnMouseButtonHold(this, MouseButton.Middle);

            this._PreviousState = actualState;
        }
        #endregion
    }

    /// <summary>
    /// Delegat udalosti vyvolana tacitkem mysi.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="button"></param>
    public delegate void OnMouseButtonDelegate(object sender, MouseButton button);

    /// <summary>
    /// Delegat udalosti volany pri pohybu kurzoru mysi.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="position"></param>
    public delegate void OnMouseMoveDelegate(object sender, Vector2 position);

    /// <summary>
    /// Identifikace tlacitka.
    /// </summary>
    public enum MouseButton : byte
    {
        Left = 0, 
        Right = 1,
        Middle = 2
    }
}
